LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY testbench IS
   PORT(
       clk,reset	:	IN STD_LOGIC;
       part_out		: IN STD_LOGIC_VECTOR(31 DOWNTO 0);
       test_pass,result_active	:	OUT STD_LOGIC;
       part_in1, part_in2	:	OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
       part_clock	:	OUT STD_LOGIC
       );
END testbench;

ARCHITECTURE structure OF testbench IS
   
COMPONENT rom_2port IS
	PORT
	(
		address_a		: IN STD_LOGIC_VECTOR (10 DOWNTO 0);
		address_b		: IN STD_LOGIC_VECTOR (10 DOWNTO 0);
		clock		: IN STD_LOGIC  := '1';
		q_a		: OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
		q_b		: OUT STD_LOGIC_VECTOR (31 DOWNTO 0)
	);
END COMPONENT;

COMPONENT DFFE
   PORT (d   : IN STD_LOGIC;
        clk  : IN STD_LOGIC;
        clrn : IN STD_LOGIC;
        prn  : IN STD_LOGIC;
        ena	 : IN STD_LOGIC;
        q    : OUT STD_LOGIC );
END COMPONENT;

COMPONENT adder_11bit IS
	PORT
	(
		dataa		: IN STD_LOGIC_VECTOR (10 DOWNTO 0);
		datab		: IN STD_LOGIC_VECTOR (10 DOWNTO 0);
		result		: OUT STD_LOGIC_VECTOR (10 DOWNTO 0)
	);
END COMPONENT;

COMPONENT decoder IS
	PORT
	(
		data		: IN STD_LOGIC_VECTOR (0 DOWNTO 0);
		eq0		: OUT STD_LOGIC ;
		eq1		: OUT STD_LOGIC 
	);
END COMPONENT;

COMPONENT rom_1port IS
	PORT
	(
		address		: IN STD_LOGIC_VECTOR (10 DOWNTO 0);
		clock		: IN STD_LOGIC  := '1';
		q		: OUT STD_LOGIC_VECTOR (31 DOWNTO 0)
	);
END COMPONENT;

SIGNAL found_delim	:	boolean;
SIGNAL state, state_next, set_in1, set_in2, ce_in1, ce_in2 :	STD_LOGIC;
SIGNAL port_ptr, port_ptr_next, data_ptr, inc, output_ptr, output_ptr_next	:	STD_LOGIC_VECTOR (10 DOWNTO 0);
SIGNAL port_no, data, desired_output, clock_delim_port, clock_delim_data	:	STD_LOGIC_VECTOR (31 DOWNTO 0);

BEGIN

-- FSM logic

state_reg: DFFE port map(state_next,clk,not reset,'1','1',state);

clock_delim_port <= "11111111111111111111111111111111"; 
clock_delim_data <= "11111111111111111111111111111111"; 
found_delim <= port_no = clock_delim_port AND data = clock_delim_data;
state_next <= '1' when state='0' AND found_delim else '0';
part_clock <= state_next;

-- input side

test_case_memory: rom_2port port map(port_ptr,data_ptr,not clk,port_no,data);

g1: for n in 10 downto 0 generate
	test_case_counter: DFFE port map(port_ptr_next(n),clk,not reset,'1',not state and not state_next,port_ptr(n));
end generate;

data_ptr_adder: adder_11bit port map(port_ptr,"00000000001",data_ptr);

adder: adder_11bit port map(port_ptr,inc,port_ptr_next);
inc <= "00000000010";

input_decoder: decoder port map(port_no(0 downto 0),set_in1,set_in2);
ce_in1 <= '1' when set_in1='1' AND state='0' AND not found_delim else '0';
ce_in2 <= '1' when set_in2='1' AND state='0' AND not found_delim else '0';

g2: for n in 31 downto 0 generate
	reg_in1: dffe port map(data(n),clk,'1','1',ce_in1,part_in1(n));
	reg_in2: dffe port map(data(n),clk,'1','1',ce_in2,part_in2(n));
end generate;
   
-- output side   

desired_output_memory: rom_1port port map(output_ptr,clk,desired_output);
output_ptr_adder: adder_11bit port map(output_ptr,"00000000001",output_ptr_next);

g3: for n in 10 downto 0 generate
	desired_output_counter: DFFE port map(output_ptr_next(n),clk,not reset,'1',state,output_ptr(n));
end generate;

--delay part_clock so result_active is asserted on next clock cycle
result_active_delay: dffe port map(state_next,clk,'1','1','1',result_active);

test_pass <= '1' when desired_output = part_out else '0';

END structure;